package Lab.Five.WallOfClutter;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;


public class Lab5WallOfClutterReadActivity extends Activity 
{
	// Fields.
	private List<Message> m_messageList;
	private boolean m_downloading = true;
	private boolean m_storing = true;
	private TextView m_textView;
	private DatabaseHelper m_dh;
	private int m_numOfMessagesInDB;
	private List<Message> m_databaseList;
	
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) 
	{
	    super.onCreate(savedInstanceState);
	    setContentView(R.layout.mainread);
	    
	    m_textView = (TextView)findViewById(R.id.textView);
	    
	    String text = "Loading messages...";
	    
	    m_textView.setText(text);
	    
	    m_messageList = new ArrayList<Message>();
	    
	    m_dh = new DatabaseHelper(this);
	    //m_dh.deleteAll();
	    m_databaseList = m_dh.selectAll();
	    
	    m_numOfMessagesInDB = m_dh.getNumOfMessages();
	    
	    if (m_numOfMessagesInDB > 0)
	    {
	    	text = "";
	    }
	    
	    for (Message mess : m_databaseList)
	    {
	    	text = text + mess.toString() + "\n";
	    }
	    
	    m_textView.setText(text);
	    
	    // Check for new messages.
	    new DownloadNewMessages().execute(); // Parameter should contain the ID:s of all existing messages.
	    
	    
	    // When the download is finished start storing.
	    if (m_downloading == false)
	    {
	    	ErrorHandling.newDebugEvent("m_downloading = false//Number of elements: " + m_messageList.size());
	    }
	    
	    // When the storing finished return the messages to the main activity.
	    if (m_storing == false)
	    {
	    	
	    }
	}
	
	// TODO: Need to fix parameters for AsyncTask.
	private class DownloadNewMessages extends AsyncTask<Void, Integer, List<Message>>
	{
		@Override
		protected List<Message> doInBackground(Void... params) 
		{
			ErrorHandling.newDebugEvent("IDs start at 1 not 0 hence 1 less element than MAXID.");
			
			List<Message> oldMessagesList = m_databaseList;
			List<Integer> idList = new ArrayList<Integer>();
			List<Message> newMessagesList = null;
			List<Message> returnList = new ArrayList<Message>();
			
			// Download the new messages.
			Client client = new Client();
			client.run();
				
			int maxId = client.getMaxId();
				
			try
			{
				if (maxId >= 1)
				{
					// Get a list of IDs that already exists.
					for (Message mess : oldMessagesList)
					{
						idList.add(mess.getId());
					}
					
					// Get a new list of messages.
					newMessagesList = client.getNewMessages(maxId, idList);
					
					// Add the old messages to the returnList
					for (Message mess : oldMessagesList)
					{
						returnList.add(mess);
					}
					
					// Add the new messages to the returnList
					for (Message mess : newMessagesList)
					{
						returnList.add(mess);
					}
	
					// Sort the list.
					Collections.sort(returnList, new MessagesByIdComparer());
				}
				
				// Store the messages.
				for (Message mess : returnList)
				{
					if (idList.contains(mess.getId()) == false)
					{
						m_dh.insertMessage(mess);
					}
				}
			}
			catch(Exception e)
			{
				ErrorHandling.newDebugErrorEvent("Lab5WallOfClutterGetMess//DownloadNewMessages//tryCatch: Exception", e.toString());
			}
			return returnList;
		}
		
		protected void onPostExecute(List<Message> resultList) 
		{
			ErrorHandling.newDebugEvent("OnPostExecute//Number of elements: " + resultList.size());
			m_messageList = resultList;
			m_downloading = false;
			
			String text = "";
			
			for (Message mess : m_messageList)
			{
				text = text + mess.toString() + "\n";
			}
			
			Context context = getApplicationContext();
			int duration = 5000;
			
			String toastText = "New messages downloaded: " + (resultList.size() - m_numOfMessagesInDB);
			Toast toast = Toast.makeText(context, toastText, duration);
			toast.show();
			
			m_textView.setText(text);
		}
	}

	
	private class Client implements Runnable
	{
		// Fields.
		private String IP = "194.47.174.57";
		private int PORT = 9050;
		private InetAddress m_serverAddr = null;
		private DatagramSocket m_socket = null;
		private byte[] m_buff = null;
		private DatagramPacket m_packet = null;
		
		public void run() 
		{
			try
			{
		        // Set the server address.
				m_serverAddr = InetAddress.getByName(IP);
				
				// Instantiate the socket.
				m_socket = new DatagramSocket();
			}
			catch (Exception e)
			{
				ErrorHandling.newDebugErrorEvent("Lab5WallOfClutterGetMess//DownloadNewMessages//Client//tryCatch: Exception", e.toString());
			}
		}
		
		public int getMaxId()
		{
			try
			{
				// Data to be sent.
				m_buff = ("MAXID;").getBytes();
					
				// Create the packet.
				m_packet = new DatagramPacket(m_buff, m_buff.length, m_serverAddr, PORT);
					
				// Send the data.
				m_socket.send(m_packet);
					
				byte[] message = new byte[1500];
				m_packet = new DatagramPacket(message, message.length);
					
				m_socket.receive(m_packet);
					
				String text = new String(m_packet.getData());
					
				// Split away the extra data that was added to fill the byte array.
				text = text.split(";")[0];
					
				// Split so you only get the ID.
				int tempId = Integer.valueOf(text.split(" ")[1]);
				
					
				Log.d("debug-event", text.split(" ")[1]);
					
				ErrorHandling.newDebugEvent("Lab5WallOfClutterGetMess//DownloadNewMessages//Client//MAXID: " + tempId);
					
				return tempId;
			}
			catch (Exception e)
			{
				Log.d("debug-event", e.toString());
				ErrorHandling.newDebugErrorEvent("Lab5WallOfClutterGetMess//DownloadNewMessages//Client//tryCatch: Exception", e.toString());
			}
			return -1;
		}
		
		public List<Message> getNewMessages(int a_maxId, List<Integer> a_idList)
		{
			List<Message> messageList = new ArrayList<Message>();
			
			try
			{
				for (int i = 1; i <= a_maxId; i++)
				{
					if (a_idList.contains(i) == false)
					{
						String dataString = "GETID " + i + ";";
							
						// Data to be sent.
						m_buff = (dataString).getBytes();
						
						// Create the packet.
						m_packet = new DatagramPacket(m_buff, m_buff.length, m_serverAddr, PORT);
						
						// Send the data.
						m_socket.send(m_packet);
						
						byte[] message = new byte[1500];
						m_packet = new DatagramPacket(message, message.length);
						
						m_socket.receive(m_packet);
						
						String text = new String(m_packet.getData());
						
						// Split at empty space to get the message length.
						String messageInfo = text.split(";")[0];
						
						int messageLength = Integer.valueOf(messageInfo.split(" ")[2]);
						int messageId = Integer.valueOf(messageInfo.split(" ")[1]);
						
						// Get only the message part of the text.
						int elements = text.split(";").length;
						String messageText = "";
						
						// If you get more than 2 elements it means the message contains more than one ; so add it back.
						if (elements > 2)
						{
							for (int z = 1; z < elements; z++)
							{
								messageText = messageText + text.split(";")[z];
							}
						}
						else
						{
							messageText = text.split(";")[1];
						}
	
						//substring the message length.
						messageText = messageText.substring(0, messageLength);
						
						Message messageObject = new Message(messageId, messageText);
						
						messageList.add(messageObject);
					}
				}
			}
			catch (Exception e)
			{
				ErrorHandling.newDebugErrorEvent("Lab5WallOfClutter//DownloadNewMessages//Client//tryCatch: Exception", e.toString());
			}
			return messageList;
		}
	}
	
	private class MessagesByIdComparer implements Comparator<Message>
	{

		public int compare(Message messageOne, Message messageTwo) 
		{
			int x = messageOne.getId();
			int y = messageTwo.getId();
			
			if (x > y)
			{
				return 1;
			}
			else if (y > x)
			{
				return -1;
			}
			else
			{
				return 0;
			}
		}
		
	}
}
